package com.apes.fn.mdm.purchase;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.tms.model.Site;
import com.apes.fn.tms.repository.SiteRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.logger.ApesLogger;
import com.apes.framework.jpa.logger.ApesLoggerRepository;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.outbox.OutboxPayloadWrapper;
import com.apes.framework.plugin.outbox.OutboxSubscriberService;
import com.apes.framework.plugin.outbox.annotation.OutboxSubscriber;
import com.apes.framework.rop.converter.DateUtils;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.EventUtil;
import com.apes.pi.service.PiManager;
import com.apes.scm.masterdata.contrast.model.ContrastPartyCode;
import com.apes.scm.masterdata.contrast.repository.ContrastPartyCodeRepository;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.masterdata.stock.model.Location;
import com.apes.scm.masterdata.stock.repository.LocationRepository;
import com.apes.scm.rbac.model.User;
import com.apes.scm.rbac.repository.UserRepository;
import org.apache.commons.collections.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 功能：采购组
 *
 * @author Linwz
 * @create 2021-02-24 10:35
 */
@Service("purchasingGroupService")
public class PurchasingGroupService extends DomainService {
    @Autowired
    public PurchasingGroupRepository purchasingGroupRepository;
    @Autowired
    public PartyRoleRepository partyRoleRepository;
    @Autowired
    private OutboxSubscriberService outboxSubscriberService;
    @Autowired
    private PiManager piManager;
    @Autowired
    private DeptRepository deptRepository;
    @Autowired
    private ContrastPartyCodeRepository contrastPartyCodeRepository;
    @Autowired
    private LocationRepository locationRepository;
    @Autowired
    private SiteRepository siteRepository;

    public PurchasingGroup save(SimpleRequest request) {
        PurchasingGroup purchasingGroup = request.getO(PurchasingGroup.class);
        purchasingGroup = this.getOperableLits(purchasingGroup);
        PurchasingGroup result = purchasingGroupRepository.saveAndFlush(purchasingGroup);
        result.setOperableLits(purchasingGroup.getOperableLits());
        createContrastPartyCode(result);
        synCGZ(result);
        return purchasingGroup;
    }

    public void createContrastPartyCode(PurchasingGroup purchasingGroup) {
        if (purchasingGroup.getOperables() == null) return;
        purchasingGroup.getOperables().forEach(partyRole -> {
            List<ContrastPartyCode> contrastPartyCodeList = contrastPartyCodeRepository.findAll(JpaDsl.toCriteriaByEq("party.id", partyRole.getParty().getId()));
            if (contrastPartyCodeList.size() == 0) {
                ContrastPartyCode contrastPartyCode = new ContrastPartyCode();
                contrastPartyCode.setParty(partyRole.getParty());
                contrastPartyCode.setRyid(partyRole.getId());
                contrastPartyCodeRepository.saveAndFlush(contrastPartyCode);
            }else {
                if (contrastPartyCodeList.get(0).getRyid() == null) {
                    contrastPartyCodeList.get(0).setRyid(partyRole.getId());
                    contrastPartyCodeRepository.saveAndFlush(contrastPartyCodeList.get(0));
                }

            }
        });
    }

    public PurchasingGroup getOperableLits(PurchasingGroup purchasingGroup){
        // 添加中间表信息
        List<JSONObject> operableLits = purchasingGroup.getOperableLits();
        if (operableLits != null) {
            List<PartyRole> operables = new ArrayList<>();
            operableLits.stream().forEach(
                    (postJ) -> {
                        PartyRole company = partyRoleRepository.findOne(postJ.getString("id"));
                        operables.add(company);
                    }
            );
            purchasingGroup.setOperables(operables);
        }
        return purchasingGroup;
    }

    public List<PurchasingGroup> findAll(SimpleRequest request) {
        return  purchasingGroupRepository.findAll();
    }



    public PurchasingGroup update(SimpleRequest request) {
        PurchasingGroup purchasingGroup = request.getO(PurchasingGroup.class);
        PurchasingGroup purchasingGroupOld = this.findOne(purchasingGroup.getId());

        purchasingGroup = this.getOperableLits(purchasingGroup);
        purchasingGroup.setDepts(purchasingGroupOld.getDepts());
        purchasingGroup.setSuppliers(purchasingGroupOld.getSuppliers());
        PurchasingGroup result = purchasingGroupRepository.saveAndFlush(purchasingGroup);
        result.setOperableLits(purchasingGroup.getOperableLits());
        createContrastPartyCode(result);
        synCGZ(result);
        return result;
    }

    public String delete(SimpleRequest request) throws Exception  {

        String id = request.get("id");
        long versions = (Long) request.get("version");

        PurchasingGroup purchasingGroup = purchasingGroupRepository.findOne(id);
        if (purchasingGroup == null) throw new RuntimeException("采购组【" + id + "】在系统中不存在。");
        if (purchasingGroup.getVersion() != versions) throw new RuntimeException("记录已更新或已删除，请重新提交！");
        try {
            purchasingGroupRepository.delete(purchasingGroup);
        }catch (Exception e){
            throw new RuntimeException("记录已被使用,不可删除！");
        }
        synCGZByDelete(purchasingGroup);
        return "删除成功";


    }

    public Page<PurchasingGroup> findAllPage(SimpleRequest request){
        List<Map> filters = request.get("condition");
        return purchasingGroupRepository.findAll(JpaDsl.toCriteria(filters), PageRequest.of(request.get("page"), request.get("size")));
    }

    public PurchasingGroup findOne(String id) {
        return purchasingGroupRepository.findOne(id);
    }



    /*
     * 定接入商 数据格式化给前端
     * */
    public JSONObject findAllForUi(SimpleRequest request) {
        JSONObject ob = request.getJO();
        JSONArray jsonArray = ob.getJSONArray("content");


        jsonArray.forEach(jsonObject ->{
            String string = jsonObject.toString();
            JSONObject json = (JSONObject)jsonObject;
            PurchasingGroup purchasingGroup = JSONObject.parseObject(string, PurchasingGroup.class);
            List<PartyRole> operables = purchasingGroup.getOperables();
            if (operables != null) {
                List operableLits = new ArrayList();
                operables.stream().forEach(
                        (company) -> {
                            JSONObject postJo = new JSONObject();
                            postJo.put("id", company.getId());
                            postJo.put("name", company.getName());
                            operableLits.add(postJo);
                        }
                );
                purchasingGroup.setOperableLits(operableLits);
                json.put("operableLits",operableLits);
            }

        });
        return ob;

//        Page<PurchasingGroup> purchasingGroupPage = request.getO(Page.class);
//        purchasingGroupPage.getContent().stream().forEach(
//                (purchasingGroup) -> {
//                    List<PartyRole> operables = purchasingGroup.getOperables();
//                    if (operables != null) {
//                        List operableLits = new ArrayList();
//                        operables.stream().forEach(
//                                (company) -> {
//                                    JSONObject postJo = new JSONObject();
//                                    postJo.put("id", company.getId());
//                                    postJo.put("name", company.getName());
//                                    operableLits.add(postJo);
//                                }
//                        );
//                        purchasingGroup.setOperableLits(operableLits);
//                    }
//                }
//        );
//        return purchasingGroupPage;
    }


    /**
     * 采购组同步到旧系统
     *
     * @param purchasingGroup
     */
    public String synCGZ(PurchasingGroup purchasingGroup) {
        JSONObject CGZ = new JSONObject();
        CGZ.put("CGZID", purchasingGroup.getId());
        CGZ.put("CGZMC", purchasingGroup.getName());
        CGZ.put("BZ", purchasingGroup.getRemark());
        CGZ.put("YXBJ", purchasingGroup.isValid() ? 1 : 0);
        CGZ.put("XNBJ", purchasingGroup.isVirtual()? 1 : 0);
        CGZ.put("TS01", DateUtils.format(purchasingGroup.getLastUpdatedStamp(), "yyyyMMdd.HHmmss.SSS"));
        CGZ.put("LRR", "yyadmin");
        CGZ.put("LRRQ_SJ", DateUtil.format(purchasingGroup.getLastUpdatedStamp(), "yyyy-MM-dd HH:mm:ss"));

//        CGZ.put("XNBJ", purchasingGroup.isVirtual() ? 1 : 0);
        if (purchasingGroup.getSite()!=null){
            CGZ.put("ZDID", purchasingGroup.getSite().getId());
            CGZ.put("ZDMC", purchasingGroup.getSite().getName());
            CGZ.put("WLCKID", purchasingGroup.getSite().getPhyDepot().getOrigin());
            CGZ.put("WLCKMC", purchasingGroup.getSite().getPhyDepot().getName());
        }

//        CGZ.put("KCZRY", purchasingGroup.getCreateDate());
        JSONArray CZYArray = new JSONArray();
        JSONArray MDArray = new JSONArray();
        JSONArray GYSArray = new JSONArray();
        List<PartyRole> operables = purchasingGroup.getOperables();
        List<Dept> depts = purchasingGroup.getDepts();
        List<PartyRole> suppliers = purchasingGroup.getSuppliers();
        if (operables != null){
            purchasingGroup.getOperables().forEach(partyRole -> {
                JSONObject dz = new JSONObject();
                dz.put("CGZID",purchasingGroup.getId());

                List<ContrastPartyCode> contrastPartyCodeList = contrastPartyCodeRepository.findAll(JpaDsl.toCriteriaByEq("party.id", partyRole.getParty().getId()));
                if (contrastPartyCodeList.size() == 0 || (contrastPartyCodeList.size() > 0 && contrastPartyCodeList.get(0).getRyid() == null)) {
                    throw new RuntimeException("请配置角色对照表！");
                }
                dz.put("KCZYID", contrastPartyCodeList.get(0).getRyid());
                CZYArray.add(dz);
            });
        }
        if (depts != null){
            purchasingGroup.getDepts().forEach(dept -> {
                JSONObject dz = new JSONObject();
                dz.put("CGZID",purchasingGroup.getId());
                dz.put("MDID",dept.getOrigin());
                MDArray.add(dz);
            });
        }
        if (suppliers != null){
            purchasingGroup.getSuppliers().forEach(partyRole -> {
                JSONObject dz = new JSONObject();
                dz.put("CGZID",purchasingGroup.getId());
                dz.put("GYSID",partyRole.getParty().getOrigin());
                GYSArray.add(dz);
            });
        }

        CGZ.put("CGZKCZYDZB", CZYArray);
        CGZ.put("CGZMDDZB", MDArray);
        CGZ.put("CGZGYSDZB", GYSArray);
        String topic = "event:cm.purchasingGroup.synCGZ";
        String returnData = EventUtil.sendSynEvent(this, topic, CGZ).stream().findFirst().get().toString();
        return returnData;
    }


    /**
     * 删除采购组同步到旧系统
     *
     * @param purchasingGroup
     */
    public String synCGZByDelete(PurchasingGroup purchasingGroup) {
        JSONObject CGZ = new JSONObject();
        CGZ.put("CGZID", purchasingGroup.getId());
        String topic = "event:cm.purchasingGroup.synCGZByDelete";
        String returnData = EventUtil.sendSynEvent(this, topic, CGZ).stream().findFirst().get().toString();
        return returnData;
    }



    /*********************************************采购组配置*****************************************************************/

    /**
     * 保存采购组门店
     * @param request
     */
    public String savePurchasingDept(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        Map<String, Object> condi = new HashMap<>();
        String deptId = getJO.getJSONObject("dept_id").getString("id");
        String purchsingId = getJO.getJSONObject("purchasing_id").getString("id");
        condi.put("DEPT_ID", deptId);
        condi.put("PURCHASING_ID", purchsingId);
        List purchasingDept = purchasingGroupRepository.findAll("SELECT * FROM CM_PURCHASING_DEPT WHERE PURCHASING_ID = :PURCHASING_ID AND DEPT_ID = :DEPT_ID", condi);
        if (purchasingDept.size() > 0) throw new RuntimeException("该配置已存在");
        purchasingGroupRepository.exec("INSERT INTO CM_PURCHASING_DEPT VALUES(:PURCHASING_ID, :DEPT_ID)", condi);

        insertLog(request.getPerson(), deptId, purchsingId, "新增采购组门店配置");

        // 同步老框架
        condi.put("DEPT_ID", deptRepository.findOne(deptId).getOrigin());
        appendSynData("S", "CM_CGZ_MD", "CGZID", "MDID", "PURCHASING_ID","DEPT_ID",
                "采购组配置同步老框架保存, 门店：" + deptId, condi);
        return "success";
    }

    /**
     * 保存采购组供应商
     * @param request
     */
    public String savePurchasingSupplier(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        Map<String, Object> condi = new HashMap<>();
        String supplierId = getJO.getJSONObject("supplier_id").getString("id");
        String purchsingId = getJO.getJSONObject("purchasing_id").getString("id");
        condi.put("SUPPLIER_ID", supplierId);
        condi.put("PURCHASING_ID", purchsingId);
        List purchasingSupplier = purchasingGroupRepository.findAll("SELECT * FROM CM_PURCHASING_SUPPLIER WHERE PURCHASING_ID = :PURCHASING_ID AND SUPPLIER_ID = :SUPPLIER_ID", condi);
        if (purchasingSupplier.size() > 0) throw new RuntimeException("该配置已存在");
        purchasingGroupRepository.exec("INSERT INTO CM_PURCHASING_SUPPLIER VALUES(:PURCHASING_ID, :SUPPLIER_ID)", condi);

        insertLog(request.getPerson(), supplierId, purchsingId, "新增采购组供应商配置");

        // 同步老框架
        condi.put("SUPPLIER_ID", partyRoleRepository.findOne(supplierId).getParty().getOrigin());
        appendSynData("S", "CM_CGZ_GYS", "CGZID", "GYSID", "PURCHASING_ID", "SUPPLIER_ID",
                "采购组配置同步老框架保存, 供应商：" + supplierId, condi);
        return "success";
    }

    /**
     * 删除采购组门店
     * @param request
     * @return
     */
    public String deletePurchasingDept(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        Map<String, Object> condi = new HashMap<>();
        String deptId = getJO.getJSONObject("dept_id").getString("id");
        String purchsingId = getJO.getJSONObject("purchasing_id").getString("id");
        condi.put("DEPT_ID", deptId);
        condi.put("PURCHASING_ID", purchsingId);
        int count = purchasingGroupRepository.exec(" DELETE FROM CM_PURCHASING_DEPT WHERE PURCHASING_ID = :PURCHASING_ID AND DEPT_ID = :DEPT_ID ", condi);
        if (count == 0) throw new RuntimeException("删除失败！未找到对应数据。");
        insertLog(request.getPerson(), deptId, purchsingId, "删除采购组门店配置");

        // 同步老框架
        condi.put("DEPT_ID", deptRepository.findOne(deptId).getOrigin());
        appendSynData("D", "CM_CGZ_MD", "CGZID", "MDID", "PURCHASING_ID","DEPT_ID",
                "采购组配置同步老框架删除, 门店：" + deptId, condi);
        return "success";
    }

    /**
     * 删除采购组供应商
     * @param request
     * @return
     */
    public String deletePurchasingSupplier(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        Map<String, Object> condi = new HashMap<>();
        String supplierId = getJO.getJSONObject("supplier_id").getString("id");
        String purchsingId = getJO.getJSONObject("purchasing_id").getString("id");
        condi.put("SUPPLIER_ID", supplierId);
        condi.put("PURCHASING_ID", purchsingId);
        int count = purchasingGroupRepository.exec("DELETE FROM CM_PURCHASING_SUPPLIER WHERE PURCHASING_ID = :PURCHASING_ID AND SUPPLIER_ID = :SUPPLIER_ID", condi);
        if (count == 0) throw new RuntimeException("删除失败！未找到对应数据。");
        insertLog(request.getPerson(), supplierId, purchsingId, "删除采购组供应商配置");

        // 同步老框架
        condi.put("SUPPLIER_ID", partyRoleRepository.findOne(supplierId).getParty().getOrigin());
        appendSynData("D", "CM_CGZ_GYS", "CGZID", "GYSID", "PURCHASING_ID", "SUPPLIER_ID",
                "采购组配置同步老框架删除, 供应商：" + supplierId, condi);
        return "success";
    }

    /**
     * 记录操作日志
     * @param partyRole
     * @param param1
     * @param param2
     * @param operator
     */
    private void insertLog(PartyRole partyRole, String param1, String param2, String operator) {
        User user = SpringManager.getBean(UserRepository.class).findByPartyRole(partyRole).get(0);
        ApesLogger apesLogger = new ApesLogger();
        apesLogger.setOperator_id(user.getId());
        apesLogger.setCreateDate(new Date());
        apesLogger.setBusinessDate(new Date());
        apesLogger.setBusinessType("PurchasingGroup");
        apesLogger.setOperate(operator);
        apesLogger.setRemark(param1 + ";" + param2);
        SpringManager.getBean(ApesLoggerRepository.class).save(apesLogger);
    }

    /**
     * 采购组配置查找
     * @param request
     * @return
     */
    public Page<?> findMasterData(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        String type = request.getJO().getJSONObject("group").getJSONArray("filters").getJSONObject(0).getString("value");
        String value = getJO.getString("key");
        List<Map> reuslt = new ArrayList<>();
        if ("deptId".equals(type)) {
            reuslt = purchasingGroupRepository.queryLikePurchasingGroupDept(value, value);
        } else if ("supplierId".equals(type)) {
            reuslt = purchasingGroupRepository.queryLikeSupplierInfo(value, value);
        } else if ("purchasingGroup".equals(type)) {
            reuslt = purchasingGroupRepository.queryLikePurchasingGroup(value, value);
        }
        Pageable pageable = PageRequest.of(request.get("page"), request.get("size"));
        PageImpl<Object> pPage = new PageImpl(reuslt, pageable, reuslt.size() == 0 ? 0 : reuslt.size());
        return pPage;
    }

    /**
     * 采购组配置界面查找数据
     * @param request
     * @return
     */
    public JSONObject getPuchasingGroupList(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        String id = getJO.getJSONObject("typeList").getString("ID");
        String type = getJO.getString("type");

        JSONObject returnData = new JSONObject();
        if ("deptId".equals(type)) {
            List<Map> getPurchasingGroupDeptList = purchasingGroupRepository.queryPurchasingGroupDept(id);
            if (getPurchasingGroupDeptList.size() == 0) throw new RuntimeException("未找到相关数据");
            returnData.put("depts", getPurchasingGroupDeptList);
            returnData.put("suppliers", purchasingGroupRepository.accordingToDeptGetSupplier(id));
            returnData.put("purchasingGroupItem", purchasingGroupRepository.accordingToDeptGetPurchasingGroup(id));

        } else if ("supplierId".equals(type)) {
            List<Map> getPurchasingGroupSupplierList = purchasingGroupRepository.queryPurchasingGroupSupplier(id);
            if (getPurchasingGroupSupplierList.size() == 0) throw new RuntimeException("未找到相关数据");
            returnData.put("depts", purchasingGroupRepository.accordingToSupplierGetDept(id));
            returnData.put("suppliers", getPurchasingGroupSupplierList);
            returnData.put("purchasingGroupItem", purchasingGroupRepository.accordingToSupplierGetPurchasingGroup(id));

        } else if ("purchasingGroup".equals(type)) {
            List<Map> getPurchasingGroupList = purchasingGroupRepository.queryPurchasingGroup(id);
            if (getPurchasingGroupList.size() == 0) throw new RuntimeException("未找到相关数据");
            returnData.put("depts", purchasingGroupRepository.accordingPurchasingGroupGetDept(id));
            returnData.put("suppliers", purchasingGroupRepository.accordingPurchasingGroupGetSupplier(id));
            returnData.put("purchasingGroupItem", getPurchasingGroupList);
        }
        return returnData;
    }

    /**
     * 拼接采购组数据同步到老框架
     * @param type
     * @param table
     * @param column1
     * @param column2
     * @param newColumn1
     * @param newColumn2
     * @param aggregateId
     * @param condi
     */
    private void appendSynData(String type, String table, String column1, String column2, String newColumn1, String newColumn2, String aggregateId, Map condi) {
        JSONObject data = new JSONObject();
        data.putAll(condi);
        data.put("TYPE", type);
        data.put("TABLE", table);
        data.put("COLUMN1", column1);
        data.put("COLUMN2", column2);
        data.put("NEW_COLUMN1", newColumn1);
        data.put("NEW_COLUMN2", newColumn2);
        outboxSubscriberService.commonSendRequest("local:mdm.purchasingGroupService.synPurchaingGroupConfiguration", aggregateId, data);
    }

    @OutboxSubscriber(id="local:mdm.purchasingGroupService.synPurchaingGroupConfiguration", name="采购组配置同步")
    private void synPurchaingGroupConfiguration(OutboxPayloadWrapper outboxPayloadWrapper) {
        JSONObject resultObj = piManager.synErp("mdmCgzService.synCGZRelatedConfiguration", outboxPayloadWrapper.getPayload());
    }



    public JSONObject findPurchaseOrderSite(SimpleRequest request) {
        JSONObject jo = request.getJO();
        String purchasingGroupId = jo.getString("purchasingGroupId");
        String locationId = jo.getString("locationId");
        PurchasingGroup purchasingGroup = purchasingGroupRepository.findOne(purchasingGroupId);
        JSONObject result = new JSONObject();
        if (purchasingGroup.isVirtual()) {
            Location location = locationRepository.findOne(locationId);
            result.put("phyDepotAddress",location.getPhyDepot().getAddress());
            List<Site> sites = siteRepository.findAll(JpaDsl.toCriteriaByEq("phyDepot",location.getPhyDepot()));
            if (sites.size() >0){
                result.put("siteName",sites.get(0).getName());
                result.put("siteId",sites.get(0).getId());
            }
        }else {
            result.put("siteName",purchasingGroup.getSite() != null?purchasingGroup.getSite().getName():null);
            result.put("phyDepotAddress",purchasingGroup.getSite() != null?purchasingGroup.getSite().getPhyDepot().getAddress():null);
            result.put("siteId",purchasingGroup.getSite() != null?purchasingGroup.getSite().getId():null);
        }
        return result;
    }

    public List<Map> getPurchaseGroupOperator(SimpleRequest request) {
        return purchasingGroupRepository.getPurchaseGroupOperator(request.get("purchaseingId"));
    }

    // 获取站点
    public Map queryPurchaseGroupSite(SimpleRequest request) {
        Map getJO = request.getMap();
        PurchasingGroup purchasingGroup = purchasingGroupRepository.findOne(getJO.get("id").toString());
        Map returnData = new HashedMap();
        if (purchasingGroup.isVirtual()) {
            List locationIds = new ArrayList();
            locationIds.add(getJO.get("locationId").toString());
            Site site = siteRepository.oldQrySite(locationIds);
            returnData.put("siteId", site.getId());
        } else {
            returnData.put("siteId", purchasingGroup.getSite().getId());
        }
        return returnData;
    }

    public boolean accordStoreIdFind(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        String storeId = getJO.getString("storeId");
        String purchasingGroupId = getJO.getString("purchasingGroupId");
        return purchasingGroupRepository.accordPurchaseGroupIdAndDeptIdFind(purchasingGroupId, storeId).size() > 0;
    }

}
